package com.bjpowernode.config;

import com.bjpowernode.filter.TokenFilter;
import com.bjpowernode.handler.AppLogoutSuccessHandler;
import com.bjpowernode.handler.AppAccessDeniedHandler;
import com.bjpowernode.handler.AppAuthenticationFailureHandler;
import com.bjpowernode.handler.AppAuthenticationSuccessHandler;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * SecurityConfig 类是 Spring Security 的核心配置类，负责配置应用程序的安全策略。
 * 包括认证方式、授权规则、CORS跨域、CSRF防护、会话管理以及自定义处理器等安全相关配置。
 * 通过注解 @EnableMethodSecurity 开启方法级别的权限控制，@Configuration 标记为配置类。
 */
@EnableMethodSecurity // 开启方法上的注解权限检查（如 @PreAuthorize）
@Configuration // 配置Spring容器，类似传统的spring.xml配置文件
public class SecurityConfig {
    @Resource
    private AppAuthenticationSuccessHandler appAuthenticationSuccessHandler; // 认证成功处理器

    @Resource
    private AppAuthenticationFailureHandler appAuthenticationFailureHandler; // 认证失败处理器

    @Resource
    private AppLogoutSuccessHandler appLogoutSuccessHandler; // 登出成功处理器

    @Resource
    private TokenFilter tokenFilter; // JWT令牌验证过滤器

    @Resource
    private AppAccessDeniedHandler appAccessDeniedHandler; // 权限不足处理器

    /**
     * 配置密码编码器 Bean，使用 BCrypt 加密算法。
     * BCrypt 是一种强哈希算法，自动生成随机盐值，安全性高且无需手动管理盐值。
     *
     * @return PasswordEncoder 实例，用于密码的加密和验证
     */
    @Bean  // 配置Spring Bean，bean的id为方法名，类型为返回值类型
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置跨域资源共享（CORS）策略，允许前端应用跨域访问后端API。
     * 定义了允许的源、请求方法和请求头，确保前后端分离架构下的正常通信。
     *
     * @return CorsConfigurationSource 实例，提供跨域配置
     */
    @Bean // 配置跨域
    public CorsConfigurationSource configurationSource() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();

        // 跨域配置
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*")); // 允许任何来源
        corsConfiguration.setAllowedMethods(Arrays.asList("*")); // 允许任何请求方法
        corsConfiguration.setAllowedHeaders(Arrays.asList("*")); // 允许任何请求头

        // 注册跨域配置，对所有路径生效
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return urlBasedCorsConfigurationSource;
    }

    /**
     * 配置安全过滤器链，定义应用程序的安全规则和行为。
     * 包括表单登录、登出、授权规则、CSRF防护、CORS、会话管理和异常处理等配置。
     *
     * @param httpSecurity Spring Security 的 HTTP 安全配置器
     * @param configurationSource 跨域配置源
     * @return SecurityFilterChain 实例，包含所有安全配置
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, CorsConfigurationSource configurationSource) throws Exception {
        return httpSecurity
                // 配置表单登录
                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl("/api/login") // 登录请求处理地址
                            .usernameParameter("loginAct") // 登录账号参数名
                            .passwordParameter("loginPwd") // 登录密码参数名
                            .successHandler(appAuthenticationSuccessHandler) // 登录成功处理器
                            .failureHandler(appAuthenticationFailureHandler); // 登录失败处理器
                })

                // 配置登出
                .logout((logout) -> {
                    logout.logoutUrl("/api/logout") // 登出请求地址
                            .logoutSuccessHandler(appLogoutSuccessHandler); // 登出成功处理器
                })

                // 配置授权规则
                .authorizeHttpRequests((authorizeHttpRequests) -> {
                    authorizeHttpRequests
                            .anyRequest().authenticated(); // 所有请求都需要认证
                })

                // 配置CSRF
                .csrf((csrf) -> {
                    csrf.disable(); // 禁用CSRF保护，JWT认证可提供防护
                })

                // 配置CORS
                .cors((cors) -> {
                    cors.configurationSource(configurationSource); // 使用自定义跨域配置
                })

                // 配置会话管理
                .sessionManagement((sessionManagement) -> {
                    // 设置无状态会话，适合JWT认证
                    sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })

                // 添加JWT令牌验证过滤器
                .addFilterBefore(tokenFilter, LogoutFilter.class)

                // 配置异常处理
                .exceptionHandling((exceptionHandling) -> {
                    exceptionHandling.accessDeniedHandler(appAccessDeniedHandler); // 权限不足处理器
                })

                .build();
    }
}